
` include "instr_dec_defs.v"

`timescale 1ns / 1ps

module instr_dec(
	i_instr,
	i_cc,
	i_ccen,
	i_zero,
	
	o_cmd_reg_cnt,
	o_cmd_stack,
	o_sel_mux, 
	o_clr_mux,
	o_en_pl,
	o_en_map,
	o_en_vect
	
);

parameter	CMD_HOLD		= 2'b00;
parameter	CMD_PUSH		= 2'b01;
parameter	CMD_POP			= 2'b10;
parameter	CMD_RESET		= 2'b11;

parameter CMD_DEC			= 2'b01;
parameter CMD_LOAD		= 2'b10;

parameter SEL_uPC			= 2'b00;
parameter SEL_DATA		= 2'b01;
parameter SEL_STACK		= 2'b10;
parameter SEL_REGCNT	= 2'b11;

input [`ID_INSTR_WIDTH-1:0] i_instr;
input i_cc;
input i_ccen;
input i_zero;

output [1:0] o_cmd_reg_cnt;
output [1:0] o_cmd_stack;
output [1:0] o_sel_mux;

output o_clr_mux;
output o_en_pl;
output o_en_map;
output o_en_vect;

wire 	[6:0] inputs;
reg 	[9:0] outputs;

assign { o_cmd_reg_cnt, o_cmd_stack, o_sel_mux, o_clr_mux, o_en_pl, o_en_map, o_en_vect } = outputs;

assign inputs		= { i_instr, i_ccen, i_cc, i_zero }; 

always@( inputs )
begin
	casex( inputs )
//				INSTR				CCEN	CC		ZERO								REGCNT		STACK				MUXSEL		 MUXCLR	PL		MAP		VECT			
		{ `ID_INSTR_JZ,  	1'bx, 1'bx, 1'bx }: outputs = { CMD_HOLD, CMD_RESET,	SEL_uPC, 		1'b1, 1'b1, 1'b0, 1'b0 };
		
		{ `ID_INSTR_CJS, 	1'b0, 1'b1, 1'bx }: outputs = { CMD_HOLD, CMD_HOLD, 	SEL_uPC, 		1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_CJS, 	1'b0, 1'b0, 1'bx },
		{ `ID_INSTR_CJS, 	1'b1, 1'bx, 1'bx }: outputs = { CMD_HOLD, CMD_PUSH,		SEL_DATA, 	1'b0, 1'b1, 1'b0, 1'b0 };
		
		{ `ID_INSTR_JMAP, 1'bx, 1'bx, 1'bx }:	outputs = { CMD_HOLD, CMD_HOLD, 	SEL_DATA, 	1'b0, 1'b0, 1'b1, 1'b0 };
		
		{ `ID_INSTR_CJP, 	1'b0, 1'b1, 1'bx }:	outputs = { CMD_HOLD, CMD_HOLD, 	SEL_uPC, 		1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_CJP, 	1'b0, 1'b0, 1'bx },
		{ `ID_INSTR_CJP, 	1'b1, 1'bx, 1'bx }:	outputs = { CMD_HOLD, CMD_HOLD, 	SEL_DATA, 	1'b0, 1'b1, 1'b0, 1'b0 };
		
		{ `ID_INSTR_PUSH, 1'b0, 1'b1, 1'bx }:	outputs = { CMD_HOLD, CMD_PUSH, 	SEL_uPC, 		1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_PUSH, 1'b0, 1'b0, 1'bx },
		{ `ID_INSTR_PUSH, 1'b1, 1'bx, 1'bx }:	outputs = { CMD_LOAD, CMD_PUSH, 	SEL_uPC, 		1'b0, 1'b1, 1'b0, 1'b0 };
		
		{ `ID_INSTR_JSRP, 1'b0, 1'b1, 1'bx }:	outputs = { CMD_HOLD, CMD_PUSH, 	SEL_REGCNT,	1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_JSRP, 1'b0, 1'b0, 1'bx },
		{ `ID_INSTR_JSRP, 1'b1, 1'bx, 1'bx }:	outputs = { CMD_HOLD, CMD_PUSH, 	SEL_DATA,		1'b0, 1'b1, 1'b0, 1'b0 };
		
		{ `ID_INSTR_CJV, 	1'b0, 1'b1, 1'bx }:	outputs = { CMD_HOLD, CMD_HOLD, 	SEL_uPC,		1'b0, 1'b0, 1'b0, 1'b1 };
		{ `ID_INSTR_CJV,	1'b0, 1'b0, 1'bx },
		{ `ID_INSTR_CJV, 	1'b1, 1'bx, 1'bx }:	outputs = { CMD_HOLD, CMD_PUSH, 	SEL_DATA,		1'b0, 1'b0, 1'b0, 1'b1 };

		{ `ID_INSTR_JRP, 	1'b0, 1'b1, 1'bx }:	outputs = { CMD_HOLD, CMD_HOLD, 	SEL_REGCNT,	1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_JRP,	1'b0, 1'b0, 1'bx },
		{ `ID_INSTR_JRP, 	1'b1, 1'bx, 1'bx }:	outputs = { CMD_HOLD, CMD_HOLD, 	SEL_DATA,		1'b0, 1'b1, 1'b0, 1'b0 };
		
		{ `ID_INSTR_RFCT,	1'bx, 1'bx, 1'b0 }:	outputs = { CMD_DEC, 	CMD_HOLD, 	SEL_STACK,	1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_RFCT,	1'bx, 1'bx, 1'b1 }:	outputs = { CMD_HOLD, CMD_POP, 		SEL_uPC,		1'b0, 1'b1, 1'b0, 1'b0 };

		{ `ID_INSTR_RPCT,	1'bx, 1'bx, 1'b0 }:	outputs = { CMD_DEC, 	CMD_HOLD, 	SEL_DATA,		1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_RPCT,	1'bx, 1'bx, 1'b1 }:	outputs = { CMD_HOLD, CMD_HOLD, 	SEL_uPC,		1'b0, 1'b1, 1'b0, 1'b0 };

		{ `ID_INSTR_CRTN,	1'b0, 1'b1, 1'bx }:	outputs = { CMD_HOLD, CMD_HOLD, 	SEL_uPC,		1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_CRTN,	1'b0, 1'b0, 1'bx },
		{ `ID_INSTR_CRTN,	1'b1, 1'bx, 1'bx }:	outputs = { CMD_HOLD, CMD_POP,	 	SEL_STACK,	1'b0, 1'b1, 1'b0, 1'b0 };

		{ `ID_INSTR_CJPP,	1'b0, 1'b1, 1'bx }:	outputs = { CMD_HOLD, CMD_HOLD, 	SEL_uPC,		1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_CJPP,	1'b0, 1'b0, 1'bx },
		{ `ID_INSTR_CJPP,	1'b1, 1'bx, 1'bx }:	outputs = { CMD_HOLD, CMD_POP,	 	SEL_DATA,		1'b0, 1'b1, 1'b0, 1'b0 };

		{ `ID_INSTR_LDCT,	1'bx, 1'bx, 1'bx }:	outputs = { CMD_LOAD, CMD_HOLD, 	SEL_uPC,		1'b0, 1'b1, 1'b0, 1'b0 };

		{ `ID_INSTR_LOOP,	1'b0, 1'b1, 1'bx }:	outputs = { CMD_HOLD, CMD_HOLD, 	SEL_STACK,	1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_LOOP,	1'b0, 1'b0, 1'bx },
		{ `ID_INSTR_LOOP,	1'b1, 1'bx, 1'bx }:	outputs = { CMD_HOLD, CMD_POP,	 	SEL_uPC,		1'b0, 1'b1, 1'b0, 1'b0 };
		
		{ `ID_INSTR_CONT,	1'bx, 1'bx, 1'bx }:	outputs = { CMD_HOLD, CMD_HOLD, 	SEL_uPC,		1'b0, 1'b1, 1'b0, 1'b0 };

		{ `ID_INSTR_TWB,	1'b0, 1'b1, 1'b0 }:	outputs = { CMD_DEC, 	CMD_HOLD, 	SEL_STACK,	1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_TWB,	1'b0, 1'b0, 1'b0 },
		{ `ID_INSTR_TWB,	1'b1, 1'bx, 1'b0 }:	outputs = { CMD_DEC, 	CMD_POP,	 	SEL_uPC,		1'b0, 1'b1, 1'b0, 1'b0 };

		{ `ID_INSTR_TWB,	1'b0, 1'b1, 1'b1 }:	outputs = { CMD_HOLD, CMD_POP, 		SEL_DATA,		1'b0, 1'b1, 1'b0, 1'b0 };
		{ `ID_INSTR_TWB,	1'b0, 1'b0, 1'b1 },
		{ `ID_INSTR_TWB,	1'b1, 1'bx, 1'b1 }:	outputs = { CMD_HOLD, CMD_POP,	 	SEL_uPC,		1'b0, 1'b1, 1'b0, 1'b0 };

		default:													outputs = { CMD_HOLD, CMD_HOLD, 	SEL_uPC, 		1'b0, 1'b0, 1'b0, 1'b0 };

	endcase
	
end

endmodule
